# -*- coding: utf-8 -*-
import random


class MaxPack:
  def __init__(self, initValue=0):
    self.maxValue = initValue
    self.maxVar = None
    self.maxVarList = []

  def Update(self, newValue, newVar):
    if newValue > self.maxValue:
      self.maxValue = newValue
      self.maxVar = newVar
      self.maxVarList = [newVar]
    elif newValue == self.maxValue:
      self.maxVarList.append(newVar)

  def Clear(self):
    self.maxValue = 0
    self.maxVar = None


class MinPack:
  def __init__(self, initMinValue=999999999, initVar=None):
    self.initMinValue = initMinValue
    self.minValue = initMinValue
    self.initVar = initVar
    self.minVar = initVar

  def Update(self, newValue, newVar):
    if newValue < self.minValue:
      self.minValue = newValue
      self.minVar = newVar

  def Clear(self):
    self.minValue = self.initMinValue
    self.minVar = self.initVar


def RandomStr(length=16):
  return str(int(random.random() * 10 ** length))


def ListDictAppend(d, k, v):
  # type: (dict, any, any) -> None
  if k not in d:
    d[k] = []
  d[k].append(v)


def ListDictRemove(d, k, v):
  # type: (dict, any, any) -> None
  if k not in d:
    return
  if v not in d[k]:
    return
  d[k].remove(v)


def PoolRandom(poolDict, filterKey=None, count=1):
  if filterKey is None:
    filterKey = []
  pool = []
  for root, weight in poolDict.items():
    if root in filterKey:
      continue
    if type(weight) == dict:
      weight = weight[count]
    pool += [root] * weight
  return random.choice(pool)


def PoolRandomHighLevel(poolList, weightKey):
  pool = []
  for poolData in poolList:
    pool += [poolData] * weightKey(poolData)
  return random.choice(pool)


def PoolRandomMulTuple(poolList):
  pool = []
  for poolData in poolList:
    pool += [poolData[1]] * poolData[0]
  return random.choice(pool)


def GetAttrByName(obj, name):
  if not hasattr(obj, name):
    return None
  return getattr(obj, name)


def Val(num):
  try:
    if type(num) == float:
      return num
    return float(num)
  except Exception as e:
    print('[error]Val.e=', e, 'num=', num, 'type=', type(num))
    return 0


def GetNumberCN(count):
  if count >= 100000000:
    return '{}亿'.format(int(count / 100000000))
  if count >= 10000:
    return '{}万'.format(int(count / 10000))
  # if count >= 1000:
  #   return '{}千'.format(int(count / 1000))
  return '{}'.format(count)


def SameMatchByArray(xi, xj):
  assert type(xi) in [tuple, list] and type(xj) in [tuple, list], f'[error]SameMatchByArray.输入不为数组类型： xi={type(xi)}{xi}, xj={type(xj)}{xj}'
  result = {}
  for aid in range(len(xi)):
    if xi[aid] == xj[aid]:
      result[aid] = xi[aid]
  return result


def SameMatchByDict(xi, xj):
  result = {}
  for key in xi:
    if xi[key] == xj.get(key):
      result[key] = xi[key]
  return result


def GetSameMath(keySet):
  result = {}
  pool = set()
  for key1 in keySet:
    for key2 in keySet:
      if key1 == key2:
        continue
      comboKey = frozenset({key1, key2})
      if comboKey in pool:
        continue
      pool.add(comboKey)
      sameMatch = SameMatchByArray(key1, key2)  # {sameIndex: sameValue}
      # print('sameMatch=', sameMatch)
      if sameMatch:
        sameMatchItems = list(sameMatch.items())
        assert len(sameMatchItems) < 2, f'[error]GetSameMath.sameMatchItems过大，sameMatchItems={sameMatchItems}'
        frozensetSameMatch = sameMatchItems[0]
        if frozensetSameMatch not in result:
          result[frozensetSameMatch] = []
        for aid in range(len(key1)):
          if aid not in sameMatch and type(key1[aid]) in [tuple, list] and type(key2[aid]) in [tuple, list]:
            diffSameMatch = SameMatchByArray(key1[aid], key2[aid])   # {dSameIndex: dSameValue}
            # print('diffSameMatch=', diffSameMatch)
            # sameMatch.update({aid: diffSameMatch})
            result[frozensetSameMatch].append(diffSameMatch)

  return result


def DeepZ(z):
  newZ = {}
  for value, indexDict in z.items():
    # print('indexDict=', indexDict)
    newZ[value] = {}
    for indexASet, indexBList in indexDict.items():
      if indexBList:
        newIndexB = indexBList[0]
        for indexB in indexBList[1:]:
          newIndexB = SameMatchByDict(newIndexB, indexB)
        newZ[value][indexASet] = newIndexB
  return newZ
